/*******************************************************************************
 *
 *
 ******************************************************************************/
#include "bsp.h"
#include "framework.h"

#define APP_TIM TMR4
#define APP_TIM_IRQn TMR4_IRQn
#define app_timer_isr TMR4_IRQHandler

#define APP_TIM_PERIOD 1000

/******************************************************************************
 *	                            function
 ******************************************************************************/
uint32_t app_tick_init(uint32_t TickPriority);
void app_tick_suspend(void);
void app_tick_resume(void);
uint32_t app_tick_get(void);
uint32_t app_tick_us_get(void);
void app_tick_isr(void);

/******************************************************************************
 *	                            var
 ******************************************************************************/
volatile uint32_t hal_tick_cnt = 0;
volatile uint32_t local_time = 0;
vtask_vector_type tm_task_vect;
void (*tm_task_list[8])(void);

/*******************************************************************************
 * @brief  app_tick_init
 * \param[in] none
 * \retval: none
 *******************************************************************************/
uint32_t app_tick_init(uint32_t TickPriority)
{
	uint32_t apb1,apb2;
	intx_alloc();

	// 使能定时器时钟
	intx_disable();
	RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR4);
	RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_TMR4);
	RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_TMR4);
	intx_enable();

	// 获取时钟值
	RCM_ReadPCLKFreq(&apb1, &apb2);

	// 配置
	APP_TIM->CTRL1 = 0;
	APP_TIM->CTRL2 = 0;

	APP_TIM->DIEN = 0;
	APP_TIM->STS = 0;

	/*1ms interrupt*/
	APP_TIM->PSC = (apb1 / 8000000) * 2 - 1;
	APP_TIM->AUTORLD = APP_TIM_PERIOD - 1;

	// nvic
	nvic_irq_set(APP_TIM_IRQn, 0x03, 1);

	APP_TIM->CTRL1_B.URSSEL = 1;
	APP_TIM->CTRL1_B.CNTEN  = 1;

	vtask_list_init(&tm_task_vect, tm_task_list, arr_len(tm_task_list), 0);

	APP_TIM->DIEN_B.UIEN = 1;

	return 0;
}

/*******************************************************************************
 * @brief  app_tick_suspend
 * \param[in] none
 * \retval: none
 *******************************************************************************/
void app_tick_suspend(void)
{
	APP_TIM->DIEN_B.UIEN = 0;
}

/*******************************************************************************
 * @brief  app_tick_resume
 * \param[in] none
 * \retval: none
 *******************************************************************************/
void app_tick_resume(void)
{
	APP_TIM->DIEN_B.UIEN = 1;
}

/*******************************************************************************
 * @brief  app_tick_get
 * \param[in] none
 * \retval: none
 *******************************************************************************/
uint32_t app_tick_get(void)
{
	return hal_tick_cnt;
}

/*******************************************************************************
 * @brief  app_tick_us_get
 * \param[in] none
 * \retval: none
 *******************************************************************************/
uint32_t app_tick_us_get(void)
{
	uint32_t time_us;

	intx_alloc();

	intx_disable();

	time_us = hal_tick_cnt * APP_TIM_PERIOD;

	time_us += APP_TIM->CNT & 0x0000FFFF;

	intx_enable();

	return time_us;
}

/*******************************************************************************
 * @brief  app_tick_isr
 * \param[in] none
 * \retval: none
 *******************************************************************************/
void key_scan(void);
void app_timer_isr(void)
{
	static uu8 tcnt = 0;
	
	APP_TIM->STS = 0;

	tcnt ++;
	tcnt &=7;
	
	if(tcnt == 0)
	{
		hal_tick_cnt++;
		lib_tick16_cnt++;
		lib_tick32_cnt++;
		local_time++;
		vtask_list_run_once(&tm_task_vect);
	}
}

/*******************************************************************************
 * @brief  app timer task add
 * \param[in] none
 * \retval: none
 *******************************************************************************/
void app_timer_task_add(void (*task)(void))
{
	intx_alloc();

	intx_disable();

	vtask_list_add(&tm_task_vect, task);

	intx_enable();
}

/*******************************************************************************
 * @brief  app timer task del
 * \param[in] none
 * \retval: none
 *******************************************************************************/
void app_timer_task_del(void (*task)(void))
{
	intx_alloc();

	intx_disable();

	vtask_list_del(&tm_task_vect, task);

	intx_enable();
}
